package com.ly.heart.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Optional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysDept;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.ConstUtil;
import com.ly.common.utils.erp.ReturnPage;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.heart.domain.*;
import com.ly.heart.domain.dto.KingBadHandleQueryDto;
import com.ly.heart.domain.dto.StartProcessDto;
import com.ly.common.core.domain.ActCurrentTaskVo;
import com.ly.heart.domain.vo.KingBadHandleVo;
import com.ly.heart.mapper.KingBadHandleMapper;
import com.ly.heart.service.*;
import com.ly.heart.util.ChineseToPinyin;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.system.service.ISysDeptService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

/**
 * 金蝶-不良品处理单Service业务层处理
 *
 * @author cxl
 * @date 2024-08-11
 */
@Service
public class KingBadHandleServiceImpl extends ServiceImpl<KingBadHandleMapper,KingBadHandleEntity> implements IKingBadHandleService {

    @Resource
    private KingBadHandleMapper kingBadHandleMapper;
    @Resource
    private ISysDeptService sysDeptService;
    @Resource
    private IKingBadHandleMaterialService badHandleMaterialService;
    @Resource
    private IKingBadHandleMaterialDetailService badHandleMaterialDetailService;
    @Resource
    private IActModelService actModelService;
    @Resource
    private IActTaskCommentService actTaskCommentService;
    @Resource
    private IKingCheckMaterialUseDecisionService checkMaterialUseDecisionService;

    @Override
    public AjaxResult getKingBandHandlePageList(KingBadHandleQueryDto queryDto){
        List<KingBadHandleVo> list = badHandleMaterialService.getKingBadHandlePageList(queryDto);
        if(!CollectionUtils.isEmpty(list)){
            list.forEach(kingBadHandleVo -> {
                ActTaskCommentEntity actTaskCommentEntity = actTaskCommentService.queryLastComment(kingBadHandleVo.getInstanceId());
                if ( actTaskCommentEntity != null ) {
                    kingBadHandleVo.setApprovedUser ( actTaskCommentEntity.getApprovedUser () );
                    kingBadHandleVo.setRemark ( actTaskCommentEntity.getRemark () );
                }
                ActCurrentTaskVo currentTaskVo = actModelService.getCurrentTaskByInstanceId(kingBadHandleVo.getInstanceId());
                Optional.ofNullable(currentTaskVo).ifPresent(kingBadHandleVo::setCurrentTask);
            });
        }
        Page<KingBadHandleVo> page = new Page<>(queryDto.getPage(),queryDto.getLimit());
        return AjaxResult.success(ReturnPage.getReturnPage(page,list));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult draft(KingBadHandleEntity kingBadHandle){
        if(StringUtils.isEmpty(kingBadHandle.getId())){
            String badHandleId = SnowflakeIdWorker.getInstance().nextStringId();
            Date nowDate = DateUtils.getNowDate();
            String userId = SecurityUtils.getLoginUser().getUser().getUserId();
            kingBadHandle.setId(badHandleId).setUserId(userId).setCreateTime(nowDate).setCreateName(SecurityUtils.getUsername());
            //不良品处理单单号生成
            if(StringUtils.isEmpty(kingBadHandle.getDocCode())){
                String companyId = CurrentUserUtil.getCompanyId();
                SysDept sysDept = sysDeptService.getById(companyId);
                int count = kingBadHandleMapper.queryCount();
                String countStr = String.format("%06d", count);
                String firstLetter = ChineseToPinyin.getFirstLetter(sysDept.getDeptName());
                String docCode = firstLetter.concat("_BLPCLD_").concat(countStr);
                kingBadHandle.setDocCode(docCode);
            }
            if(!CollectionUtils.isEmpty(kingBadHandle.getMaterialLists())){
                //保存物料等信息
                saveMaterialAndDetail(kingBadHandle,kingBadHandle.getMaterialLists());
            }
            //流程状态：暂存
            kingBadHandle.setState(ConstUtil.STATE_IN_DRAFT);
            boolean save = this.save(kingBadHandle);
            if(save){
                return AjaxResult.success("暂存不良品处理单成功！",kingBadHandle.getId());
            }
            return AjaxResult.error("暂存不良品处理单失败！");
        }else{
            return update(kingBadHandle);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult submit(KingBadHandleEntity kingBadHandle){
        if ( StringUtils.isBlank ( kingBadHandle.getId () ) ) {
            return AjaxResult.error ("请先暂存该单据！");
        }
        if(CollectionUtils.isEmpty(kingBadHandle.getMaterialLists())){
            return AjaxResult.error("物料信息不能为空!");
        }
        //数量检查
        checkMaterialNum(kingBadHandle.getMaterialLists());
        //删除
        removeMaterialAndDetail(kingBadHandle.getId());
        //保存物料等信息
        saveMaterialAndDetail(kingBadHandle,kingBadHandle.getMaterialLists());
        //启动审批流程
        StartProcessDto startDto = new StartProcessDto().setBusinessId(kingBadHandle.getId()).setBusinessType(kingBadHandle.getBusinessType()).setModelId(kingBadHandle.getModelId());
        startDto.setBusinessName("不良品处理单_".concat(kingBadHandle.getDocCode()));
        String instanceId = actModelService.startProcess(startDto);
        kingBadHandle.setState(ConstUtil.STATE_IN_PROCESS).setInstanceId(instanceId).setUpdateTime(DateUtils.getNowDate());
        boolean updated = this.updateById(kingBadHandle);
        if ( !updated ) {
            throw new CustomException( "提交不良品处理单失败!" );
        }
        return AjaxResult.success ( "提交不良品处理单成功!" );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult update(KingBadHandleEntity kingBadHandle){
        if(StringUtils.isEmpty(kingBadHandle.getId())){
            return AjaxResult.error("不良品处理单id不能为空！");
        }
        //删除
        removeMaterialAndDetail(kingBadHandle.getId());
        //保存物料等信息
        saveMaterialAndDetail(kingBadHandle,kingBadHandle.getMaterialLists());
        boolean updated = this.updateById(kingBadHandle);
        if ( !updated ) {
            AjaxResult.error( "修改失败!");
        }
        return AjaxResult.success ( "修改成功!",kingBadHandle.getId()  );
    }

    /**
     * 校验不良品处理单数量(检验单下推过来的)
     * 1.查找检验单决策信息为让步接收或者判退的数量，同时判断是否勾选不良品处理
     * 2.查找检验单该物料已经下推不良品处理单的数量
     * 3.勾选的数量 - 已经下推的数量 = 剩余可推数量
     * @param materialLists
     */
    private void checkMaterialNum(List<KingBadHandleMaterialEntity> materialLists){
        for(KingBadHandleMaterialEntity kingBadHandleMaterial : materialLists){
            //查询源单可下推的总数
            List<KingCheckMaterialUseDecisionEntity> useDecisionList = queryMaterialNumByCheck(kingBadHandleMaterial.getRelationId(), kingBadHandleMaterial.getSourceMaterialDetailId());
            double sumNum = useDecisionList.stream().mapToDouble(materialDecision -> Double.parseDouble(materialDecision.getNum())).sum();
            //查询已下推不良品处理单的数量
            List<KingBadHandleMaterialEntity> badHandleMaterialList = badHandleMaterialService.list(new LambdaQueryWrapper<KingBadHandleMaterialEntity>()
                .ne(KingBadHandleMaterialEntity::getBadHandleId,kingBadHandleMaterial.getBadHandleId())
                .eq(KingBadHandleMaterialEntity::getRelationId, kingBadHandleMaterial.getRelationId())
                .eq(KingBadHandleMaterialEntity::getSourceMaterialDetailId, kingBadHandleMaterial.getSourceMaterialDetailId()));
            double sumBadHandleNum = 0;
            if(!CollectionUtils.isEmpty(badHandleMaterialList)){
                sumBadHandleNum = badHandleMaterialList.stream().mapToDouble(badHandleMaterial -> Double.parseDouble(badHandleMaterial.getCheckBadNum())).sum();
            }
            //剩余可下推数量
            double surplusNum = sumNum - sumBadHandleNum;
            if(Double.parseDouble(kingBadHandleMaterial.getCheckBadNum()) > surplusNum){
                throw new RuntimeException("可下推数量不能超过检验单数量！");
            }
        }
    }

    /**
     * 根据检验单id和物料明细id查询检验单勾选了不良品处理单的数量
     * @param checkId
     * @param checkMaterialId
     * @return
     */
    private List<KingCheckMaterialUseDecisionEntity> queryMaterialNumByCheck(String checkId,String checkMaterialId){
        return checkMaterialUseDecisionService.list(
            new LambdaQueryWrapper<KingCheckMaterialUseDecisionEntity>().eq(KingCheckMaterialUseDecisionEntity::getCheckId, checkId)
            .eq(KingCheckMaterialUseDecisionEntity::getCheckMaterialId, checkMaterialId)
            .eq(KingCheckMaterialUseDecisionEntity::getIsBadHandle, true)
//            .and(wrapper -> wrapper.in(KingCheckMaterialUseDecisionEntity::getUseDecision, ConstUtil.CHECK_DECISION_CONCESSION_ACCEPT, ConstUtil.CHECK_DECISION_REJECT))
        );
    }

    /**
     * 保存不良品处理单物料和明细信息
     * @param kingBadHandle
     * @param materialLists
     */
    private void saveMaterialAndDetail(KingBadHandleEntity kingBadHandle,List<KingBadHandleMaterialEntity> materialLists){
      materialLists.forEach(badHandleMaterial -> {
          String badHandleMaterialId = SnowflakeIdWorker.getInstance().nextStringId();
          badHandleMaterial.setId(badHandleMaterialId).setBadHandleId(kingBadHandle.getId()).setUserId(kingBadHandle.getUserId()).setCreateTime(kingBadHandle.getCreateTime());
          boolean materialFlag = badHandleMaterialService.save(badHandleMaterial);
          if(!materialFlag){
              throw new RuntimeException("新增不良品处理单物料失败！");
          }
          KingBadHandleMaterialDetailEntity materialDetailEntity = badHandleMaterial.getMaterialDetail();
          Optional.ofNullable(materialDetailEntity).ifPresent(materialDetail -> {
              materialDetail.setBadHandleId(kingBadHandle.getId()).setBadHandleMaterialId(badHandleMaterialId).setUserId(kingBadHandle.getUserId()).setCreateTime(kingBadHandle.getCreateTime());
              boolean materialDetailFlag = badHandleMaterialDetailService.save(materialDetail);
              if(!materialDetailFlag){
                  throw new RuntimeException("新增不良品处理单物料明细失败！");
              }
          });
      });
    }

    /**
     * 查询金蝶-不良品处理单
     * @param id 金蝶-不良品处理单ID
     * @return 金蝶-不良品处理单
     */
    @Override
    public KingBadHandleEntity selectKingBadHandleEntityById(String id)
    {
        KingBadHandleEntity kingBadHandleEntity = kingBadHandleMapper.selectKingBadHandleEntityById(id);
        Optional.ofNullable(kingBadHandleEntity).ifPresent(kingBadHandle -> {
            List<KingBadHandleMaterialEntity> badHandleMaterialList = badHandleMaterialService.list(new LambdaQueryWrapper<KingBadHandleMaterialEntity>().eq(KingBadHandleMaterialEntity::getBadHandleId, kingBadHandle.getId()));
            if(!CollectionUtils.isEmpty(badHandleMaterialList)){
                badHandleMaterialList.forEach(badHandleMaterial -> {
                    KingBadHandleMaterialDetailEntity badHandleMaterialDetail = badHandleMaterialDetailService.getOne(new LambdaQueryWrapper<KingBadHandleMaterialDetailEntity>().eq(KingBadHandleMaterialDetailEntity::getBadHandleId, kingBadHandle.getId()).eq(KingBadHandleMaterialDetailEntity::getBadHandleMaterialId, badHandleMaterial.getId()));
                    badHandleMaterial.setMaterialDetail(badHandleMaterialDetail);
                });
            }
            kingBadHandle.setMaterialLists(badHandleMaterialList);
        });
        return kingBadHandleEntity;
    }

    /**
     * 查询金蝶-不良品处理单列表
     * @param kingBadHandleEntity 金蝶-不良品处理单
     * @return 金蝶-不良品处理单
     */
    @Override
    public List<KingBadHandleEntity> selectKingBadHandleEntityList(KingBadHandleEntity kingBadHandleEntity)
    {
        return kingBadHandleMapper.selectKingBadHandleEntityList(kingBadHandleEntity);
    }

    /**
     * 修改金蝶-不良品处理单
     * @param kingBadHandleEntity 金蝶-不良品处理单
     * @return 结果
     */
    @Override
    public int updateKingBadHandleEntity(KingBadHandleEntity kingBadHandleEntity)
    {
        kingBadHandleEntity.setUpdateTime(DateUtils.getNowDate());
        return kingBadHandleMapper.updateKingBadHandleEntity(kingBadHandleEntity);
    }

    /**
     * 封装公用的删除方法
     * @param id
     */
    private void removeMaterialAndDetail(String id){
        badHandleMaterialService.remove(new LambdaQueryWrapper<KingBadHandleMaterialEntity>().eq(KingBadHandleMaterialEntity::getBadHandleId,id));
        badHandleMaterialDetailService.remove(new LambdaQueryWrapper<KingBadHandleMaterialDetailEntity>().eq(KingBadHandleMaterialDetailEntity::getBadHandleId,id));
    }

    /**
     * 批量删除金蝶-不良品处理单
     * @param ids 需要删除的金蝶-不良品处理单ID
     * @return 结果
     */
    @Override
    public int deleteKingBadHandleEntityByIds(String[] ids)
    {
        for(String id : ids){
            removeMaterialAndDetail(id);
        }
        return kingBadHandleMapper.deleteKingBadHandleEntityByIds(ids);
    }

    /**
     * 删除金蝶-不良品处理单信息
     * @param id 金蝶-不良品处理单ID
     * @return 结果
     */
    @Override
    public int deleteKingBadHandleEntityById(String id)
    {
       removeMaterialAndDetail(id);
       return kingBadHandleMapper.deleteKingBadHandleEntityById(id);
    }

}
